﻿using System;
using System.Threading;
using System.Web;
using System.Web.Hosting;

using FireBus.Core;
using FireBus.Core.Configuration;


namespace FireBus.Web.Framework
{
	public class ExtensibleHttpApplication : HttpApplication
	{
		private static Host _Host;

		private static Router _Routes;


		protected void Application_OnStart()
		{
			var config = GetConfiguration();
			
			_Host = new Host(config);
			_Routes = new Router(_Host);

			InitializeHost(_Host);

			var asyncResult = _Host.BeginLoadAllExtensions(null, null);
			_Host.EndLoadAllExtensions(asyncResult);
		}

		virtual protected IConfiguration GetConfiguration()
		{
			return new XmlConfiguration();
		}

		virtual protected void InitializeHost(Host host)
		{
		}

		public override void Init()
		{
			base.Init();
			PostResolveRequestCache += OnPostResolveRequestCache;
		}

		private void OnPostResolveRequestCache(Object sender, EventArgs e)
		{
			var path = GetRequestPath();
			if (IsFileOrDirectoryExists(path))
			{
				return;
			}

			ProcessRequest();
		}

		private String GetRequestPath()
		{
			var path = Context.Request.AppRelativeCurrentExecutionFilePath;
			return path;
		}

		private static Boolean IsFileOrDirectoryExists(String path)
		{
			var vpp = HostingEnvironment.VirtualPathProvider;
			return
				path != "~/" &&
				vpp != null &&
				(
					vpp.FileExists(path) ||
					vpp.DirectoryExists(path)
				);
		}

		private void ProcessRequest()
		{
			var extensionAction = _Routes.RequestToAction(Context.Request);
			if (extensionAction == null)
			{
				Context.Response.StatusCode = 404;
			}
			else
			{
				var response = extensionAction.Execute(_Host, Context.Request.Params);
				Context.Response.ContentType = response.ContentType;
				Context.Response.BinaryWrite(response.Content);
			}
			Context.Response.End();
		}
	}
}
